package com.atguigu.spring.tran.service;

import com.atguigu.spring.tran.dao.AccountDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.TransactionCallbackWithoutResult;
import org.springframework.transaction.support.TransactionTemplate;

/**
 * @author yanglin
 * @create 2023-12-13 9:09 星期三
 * description:
 */
@Service
public class AccountService {
    
    @Autowired
    AccountDao accountDao;

    /**
     * 事务传播行为：
     *  - ioslation:事务隔离级别
     *   - 隔离性：多事务操作，之间不会产生影响，不考虑隔离性，会产生很多的问题。
     *     - 脏读：一个未提交的事务读取到另一个未提交事务的数据。
     *     - 不可重复读：一个未提交的事务在多次读取同一条数据，结果不一致；通常是由另一个事务在两次读取之间修改并提交了这个数据
     *     - 幻读：一个事务在读取某一范围的数据时，另一个事务在该范围内插入了新的数据，导致一个事务开到了并不存在的数据。
     * - timeout:超时时间
     *   - 事务需要在一定时间内进行提交，如果不提交就进行回滚。
     *   - 默认值 -1（不超时），设置时间是以秒为单位进行计算，
     * - readOnly:是否只读
     *   - 默认值：false（表示可以查询，也可以添加修改删除）
     *   - true：只能做查询操作，不能做修改数据的操作
     * - rollbackFor:回滚
     *   - 设置出现哪些异常后进行回滚
     * - noRollbackFor:不会滚
     *   - 出现哪些异常后不进行事务回滚
     */
    //转账的方法
    //@Transactional(timeout = -1,propagation = Propagation.REQUIRED,isolation = Isolation.REPEATABLE_READ)
    public void accountMoney(){
        //支出
        accountDao.reduceMoney();
        //模拟异常
        int i = 10 / 0;
        //收入
        accountDao.addMoney();
    }


    @Transactional
    public void accountMoney3(){
        //支出
        accountDao.reduceMoney();
        //模拟异常
        int i = 10 / 0;
        //收入
        accountDao.addMoney();
        
    }

    
    @Autowired
    TransactionTemplate transactionTemplate;
    
    /**
     * Spring 编程式事务管理
     */
    public void accountMoney2(){
        transactionTemplate.execute(new TransactionCallbackWithoutResult() {
            @Override
            protected void doInTransactionWithoutResult(TransactionStatus transactionStatus) {
                try {
                    //支出
                    accountDao.reduceMoney();

                    //模拟异常
                    int i = 10 / 0;

                    //收入
                    accountDao.addMoney();    
                }catch (Exception e){
                    
                    //如果执行过程中发生异常，回滚事务
                    transactionStatus.setRollbackOnly();
                    e.printStackTrace();
                }
            }
        });   
    }
    
}
